//
//  FileTree.cpp
//  syncer
//
//  Created by Silvtar on 11/28/12.
//  Copyright (c) 2012 Silvtar. All rights reserved.
//

#include "FileTree.h"
#include "Transport.h"
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdio.h>

//************************************************************************
//				SSTreeNode
//************************************************************************
SSTreeNode::SSTreeNode() {
	date = 0;
	isDir = false;
	size = 0;
}
//************************************************************************

int SSTreeNode::transLocal(SSTree &source, SSTree &aim) {

	std::string sourceFile = source.getPath() + relativePath;
	std::string aimFile = aim.getPath() + relativePath;

	//如果是文件，则进行拷贝
	if (false == isDir) {
		copy_file(sourceFile.c_str(), aimFile.c_str());
	}
	//如果是文件夹
	else {
		DIR * dir_ptr;
		if (NULL == (dir_ptr = opendir(aimFile.c_str()))) {
			if ((mkdir(aimFile.c_str(), 0644)) == -1)
				std::cerr << "can't creat DIR " << aimFile << std::endl;
		} else {
			closedir(dir_ptr);
		}
		for (unsigned int i = 0; i < child.size(); i++)
			child[i].transLocal(source, aim);
	}
	return 0;
}

void SSTreeNode::print() {
	for (unsigned int i = 0; i < child.size(); i++) {
		std::cout << child[i].name << std::endl;
		if (child[i].isDir)
			child[i].print();
	}
}

bool SSTreeNode::operator==(const SSTreeNode &t) {
	if (name == t.name)
		return true;
	else
		return false;
}

//************************************************************************
//				SSTree
//************************************************************************

void SSTree::printFileTree() {
	root.print();
}

int SSTree::build(std::string path) {
	this->path = path;

	root.name = "";
	root.relativePath = "";
	root.isDir = true;

	scanDirMain();

	return 0;
}

int SSTree::scanDirMain() {
	DIR * dir_ptr;              //文件夹指针
	struct dirent * direntp;    //文件结构体指针

	if ((dir_ptr = opendir(path.c_str())) == NULL) {
		std::cerr << "cannot open " << path << std::endl;
		return -1;
	} else {

		while ((direntp = readdir(dir_ptr)) != NULL) {

			SSTreeNode currentChild;	//当前正在处理的文件节点
			if (IGNORE_DOT == true)
				if ('.' == *(direntp->d_name))
					continue;

			//获得文件名
			currentChild.name = direntp->d_name;

			//获得文件相对路径
			currentChild.relativePath = root.relativePath + '/'
					+ currentChild.name;

			//获得文件大小和修改时间
			struct stat infobuf;            //文件属性结构体
			if (stat((path + currentChild.relativePath).c_str(), &infobuf)
					== -1)
				perror((path + currentChild.relativePath).c_str());
			else {
				currentChild.date = infobuf.st_mtime;
				currentChild.size = infobuf.st_size;
			}

			//获得是否目录和文件权限
			if ((infobuf.st_mode & 0170000) == 0040000)
				currentChild.isDir = true;

			//如果是目录，则进入递归
			if (true == currentChild.isDir)
				if (!(currentChild.name == "." || currentChild.name == ".."))
					scanDir(currentChild);

			//把处理好的节点加入到vector中
			root.child.push_back(currentChild);
		}
		closedir(dir_ptr);
	}

	return 0;
}

int SSTree::scanDir(SSTreeNode &currentNode) {

	DIR * dir_ptr;              //文件夹指针
	struct dirent * direntp;    //文件结构体指针

	if ((dir_ptr = opendir((path + currentNode.relativePath).c_str())) == NULL) {
		std::cerr << "cannot open " << path + currentNode.relativePath
				<< std::endl;
		return -1;
	} else {

		while ((direntp = readdir(dir_ptr)) != NULL) {
			SSTreeNode currentChild;	//当前正在处理的文件节点
			if (IGNORE_DOT == true)
				if ('.' == *(direntp->d_name))
					continue;

			//获得文件名
			currentChild.name = direntp->d_name;

			//获得文件相对路径
			currentChild.relativePath = currentNode.relativePath + '/'
					+ currentChild.name;

			//获得文件大小和修改时间
			struct stat infobuf;            //文件属性结构体
			if (stat((path + currentChild.relativePath).c_str(), &infobuf)
					== -1)
				perror((path + currentChild.relativePath).c_str());
			else {
				currentChild.date = infobuf.st_mtime;
				currentChild.size = infobuf.st_size;
			}

			//获得是否目录和文件权限
			if ((infobuf.st_mode & 0170000) == 0040000)
				currentChild.isDir = true;

			//如果是目录，则进入递归
			if (true == currentChild.isDir)
				if (!(currentChild.name == "." || currentChild.name == ".."))
					scanDir(currentChild);

			//把处理好的节点加入到vector中
			currentNode.child.push_back(currentChild);
		}
		closedir(dir_ptr);
	}

	return 0;
}
